/*
 * Copyright 2013 Alan Burlison, alan@bleaklow.com.  All rights reserved.
 * Use is subject to license terms.  See LICENSE.txt for details.
 */

#include "SPIMaster.h"

// Duemilanove.
#if defined(__AVR_ATmega328P__)

#define SPI_PORT PORTB
#define SPI_DDR  DDRB
#define SPI_PIN  PINB
#define SPI_MOSI PORTB3   // Arduino pin 11.
#define SPI_MISO PORTB4   // Arduino pin 12.
#define SPI_SCK  PORTB5   // Arduino pin 13.

// Mega.
#elif defined(__AVR_ATmega1280__)

#define SPI_PORT PORTB
#define SPI_DDR  DDRB
#define SPI_PIN  PINB
#define SPI_SCK  PORTB1   // Arduino pin 52.
#define SPI_MOSI PORTB2   // Arduino pin 51.
#define SPI_MISO PORTB3   // Arduino pin 50.

// Minimus V1 & V2
#elif defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__)

#define SPI_PORT PORTB
#define SPI_DDR  DDRB
#define SPI_PIN  PINB
#define SPI_SCK  PORTB1
#define SPI_MOSI PORTB2
#define SPI_MISO PORTB3

// Otherwise, unknown.
#else
#error "Unknown MCU type"
#endif

SPIMaster::SPIMaster(uint8_t _spcr, uint8_t _spsr, const pin_t *const _csn) :
  spcr(_spcr),
  spsr(_spsr),
  csn(_csn) {
}

// Virtual.
void SPIMaster::SPIInitPins(bool initSharedPins) {
    // Initialise the shared SPI pins.
    if (initSharedPins) {
        SET_BIT_HI(SPI_DDR, SPI_MOSI);          // Output.
        SET_BIT_LO(SPI_PORT, SPI_MOSI);         // Low.

        SET_BIT_LO(SPI_DDR, SPI_MISO);          // Input.
        SET_BIT_LO(SPI_PORT, SPI_MISO);         // No pullup.

        SET_BIT_HI(SPI_DDR, SPI_SCK);           // Output.
        SET_BIT_LO(SPI_PORT, SPI_SCK);          // Low.
    }
    SET_BIT_HI(*csn->ddr, csn->bit);            // Output.
    SET_BIT_HI(*csn->port, csn->bit);           // High.
}